package TokenRecognizer;

/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

/**
 *
 * @author jefoutta
 */
import java.io.IOException;
import java.util.*;
import java.util.logging.Level;
import java.util.logging.Logger;

public class Automata {
    private boolean deterministic;
    private Matrix<Transition> matrix;
    private LinkedList<State> stateList = new LinkedList();
    private Hashtable<String,State> stateTable = new Hashtable();
    private LinkedList<Character> symbols = new LinkedList();
    private String sigma = "";
    private String labels = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvw";

    public Automata(){
        matrix = new Matrix();
    }

    public void addFirstState(String tlabel){
        State tstate = new State(tlabel);
        stateList.addFirst(tstate);
        stateTable.put(tlabel, tstate);
        matrix.addFirstField();
    }

    public void addFirstState(State st){
        stateList.addFirst(st);
        //stateTable.put(tlabel, tstate);
        matrix.addFirstField();
    }

    public void addLastState(String tlabel){
        State tstate = new State(tlabel);
        stateList.addLast(tstate);
        stateTable.put(tlabel, tstate);
        matrix.addLastField();
    }

    public void addLastState(State st){
        stateList.addLast(st);
        matrix.addLastField();
    }

    public State getFirstState(){
        return stateList.peekFirst();
    }

    public State getLastState(){
        return stateList.peekLast();
    }

    public State getState(Integer n){
        return stateList.get(n);
    }

    public String getSigma(){
        return sigma;
    }

    public void setSigma(String s){
        sigma = s;
    }

    public void setAcceptation(State n){
        if(!stateList.get(stateList.indexOf(n)).getAcceptation())
            stateList.get(stateList.indexOf(n)).setAcceptation(true);
        else
            stateList.get(stateList.indexOf(n)).setAcceptation(false);
    }

    public void setAcceptation(Integer n){
        stateList.get(n).setAcceptation(true);
    }

    public void setDeterministic(boolean b){
        deterministic = b;
    }

    public boolean getDeterministic(){
        return deterministic;
    }

    public void setTransition(State from, State to, Transition t){
        t.setFrom(stateList.get(stateList.indexOf(from)));
        t.setTo(stateList.get(stateList.indexOf(to)));
        matrix.setElement(stateList.indexOf(from), stateList.indexOf(to), t);
    }

    public Transition getTransition(State from, State to){
        return matrix.getElement(stateList.indexOf(from), stateList.indexOf(to));
    }

    public void join(Automata tautomata){
        for(int i = 0; i < tautomata.stateList.size(); i++)
            stateList.addLast(tautomata.stateList.get(i));
        matrix.join(tautomata.matrix);
    }

    public void merge(Automata tautomata){
        for(int i = 1; i < tautomata.stateList.size(); i++)
            stateList.addLast(tautomata.stateList.get(i));
        matrix.merge(tautomata.matrix);
    }

    public void setTransition(String from, String to, Transition t){
        t.setFrom(stateList.get(stateList.indexOf(stateTable.get(from))));
        t.setTo(stateList.get(stateList.indexOf(stateTable.get(to))));
        matrix.setElement(stateList.indexOf(stateTable.get(from)), stateList.indexOf(stateTable.get(to)), t);
    }

    public Transition getTransition(String from, String to, Transition t){
        return matrix.getElement(stateList.indexOf(stateTable.get(from)), stateList.indexOf(stateTable.get(to)));
    }

    public Integer getSize(){
        return stateList.size();
    }

    public void setLabel(){
        for(int i = 0; i < stateList.size(); i++)
            stateList.get(i).setLabel("" + labels.charAt(i));
    }

    public LinkedList<State> aceptationList(){
        LinkedList<State> temp = new LinkedList();
        for(int i = 0; i < stateList.size(); i++)
            if(stateList.get(i).getAcceptation())
                temp.add(stateList.get(i));
        return temp;
    }

    public LinkedList<String> transitionList(){
        LinkedList<String> temp = new LinkedList();
        for(int i = 0; i < this.getSize(); i++)
            for(int j = 0; j < this.getSize(); j++)
                if(matrix.getElement(i, j) != null){
                    if(!symbols.contains(matrix.getElement(i, j).getLabel()))
                        symbols.addLast(matrix.getElement(i, j).getLabel());
                    temp.add("("+ matrix.getElement(i, j).getFrom().toString() + ", "+ matrix.getElement(i, j).toString() +", "+ matrix.getElement(i, j).getTo().toString() + ") ");
                }
                    
        return temp;
    }

    public String toString(){
        return matrix.getMatrix().toString();
    }

    public void toFile(String s){
        this.setLabel();
        FileManager fm = new FileManager();
        LinkedList<String> lines = new LinkedList();
        LinkedList<String> temp = this.transitionList();
        lines.add("ESTADOS = " + stateList.toString());
        lines.add("SIMBOLOS = " + symbols.toString());
        lines.add("INICIO = " + stateList.get(0).toString());
        lines.add("ACEPTACION = " + this.aceptationList().toString());
        lines.add("TRANSICION = " + temp.toString());
        //System.out.println(this.transitionList().toString());
        try {
            fm.createFile(s);
            fm.open(s);
        } catch (IOException ex) {
            Logger.getLogger(Automata.class.getName()).log(Level.SEVERE, null, ex);
        }
        for(int i = 0; i < lines.size(); i++)
            try {
            fm.writeLine(lines.get(i));
        } catch (IOException ex) {
            Logger.getLogger(Automata.class.getName()).log(Level.SEVERE, null, ex);
        }
        try {
            fm.closew();
        } catch (IOException ex) {
            Logger.getLogger(Automata.class.getName()).log(Level.SEVERE, null, ex);
        }
    }
}
